package org.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.example.config.RabbitMQConfig;
import org.example.enums.BizCodeEnum;
import org.example.enums.ProductOrderStateEnum;
import org.example.enums.StockTaskStateEnum;
import org.example.exception.BizException;
import org.example.feign.ProductOrderFeignService;
import org.example.mapper.ProductMapper;
import org.example.mapper.ProductTaskMapper;
import org.example.model.PageResult;
import org.example.model.ProductDO;
import org.example.model.ProductMessage;
import org.example.model.ProductTaskDO;
import org.example.request.LockProductRequest;
import org.example.request.OrderItemRequest;
import org.example.service.ProductService;
import org.example.util.JsonData;
import org.example.vo.ProductVO;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private ProductTaskMapper productTaskMapper;

    @Autowired
    private RabbitMQConfig rabbitMQConfig;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private ProductOrderFeignService productOrderFeignService;

    /**
     * 分页查询商品列表
     */
    @Override
    public PageResult page(int page, int size) {
        Page<ProductDO> pageInfo = new Page<>(page, size);
        Page<ProductDO> productDOPage = productMapper.selectPage(pageInfo, null);
        List<ProductVO> productVOList = productDOPage.getRecords().stream()
                .map(obj -> beanProcess(obj)).collect(Collectors.toList());
        return new PageResult(productDOPage.getTotal(), productDOPage.getPages(), productVOList);
    }

    /**
     * 根据id查询商品
     */
    @Override
    public ProductVO findById(Long productId) {
        ProductDO productDO = productMapper.selectById(productId);
        return this.beanProcess(productDO);
    }

    /**
     * 批量查询商品
     */
    @Override
    public List<ProductVO> findProductsByIdBatch(List<Long> productIdList) {
        List<ProductDO> productDOList = productMapper.selectList(new QueryWrapper<ProductDO>().in("id", productIdList));
        List<ProductVO> productVOList = productDOList.stream().map(obj -> this.beanProcess(obj)).collect(Collectors.toList());
        return productVOList;
    }

    /**
     * 锁定商品库存
     */
    @Override
    public JsonData lockProductStock(LockProductRequest lockProductRequest) {
        String outTradeNo = lockProductRequest.getOutTradeNo();
        List<OrderItemRequest> orderItemList = lockProductRequest.getOrderItemList();
        //1、查询出所有商品
        //1.1、提取所有的商品id
        List<Long> productIds = orderItemList.stream().map(OrderItemRequest::getProductId).collect(Collectors.toList());
        //1.2、根据id集合查出所有商品
        List<ProductVO> productList = this.findProductsByIdBatch(productIds);
        //1.3、将商品提取成map形式，方便获取
        Map<Long, ProductVO> productMap = productList.stream().collect(Collectors.toMap(ProductVO::getId, Function.identity()));


        for (OrderItemRequest orderItem : orderItemList) {
            //2、锁定商品库存: 调整每一个商品的stock和lock_stock
            int rows = productMapper.lockProductStock(orderItem.getProductId(), orderItem.getBuyNum());
            if (rows != 1) {
                throw new BizException(BizCodeEnum.ORDER_CONFIRM_LOCK_PRODUCT_FAIL);
            } else {
                //3、批量插入到product_task
                ProductVO productVO = productMap.get(orderItem.getProductId());
                ProductTaskDO taskDO = new ProductTaskDO();
                taskDO.setProductId(orderItem.getProductId());
                taskDO.setProductName(productVO.getTitle());
                taskDO.setBuyNum(orderItem.getBuyNum());
                taskDO.setLockState(StockTaskStateEnum.LOCK.name());
                taskDO.setOutTradeNo(outTradeNo);
                taskDO.setCreateTime(new Date());
                productTaskMapper.insert(taskDO);
                log.info("插入taskDO成功: {}", taskDO);

                ProductMessage productMessage = new ProductMessage();
                productMessage.setTaskId(taskDO.getId());
                productMessage.setOutTradeNo(outTradeNo);

                //4、发送延迟消息
                rabbitTemplate.convertAndSend(rabbitMQConfig.getStockEventExchange(),
                        rabbitMQConfig.getStockReleaseDelayRoutingKey(),
                        productMessage
                );
                log.info("发送库存锁定消息成功:{}", productMessage);
            }
        }

        return JsonData.buildSuccess();
    }

    /**
     * 释放商品库存
     */
    @Override
    public boolean releaseProductStock(ProductMessage productMessage) {
        Long taskId = productMessage.getTaskId();
        String outTradeNo = productMessage.getOutTradeNo();
        // 查询工作单状态
        ProductTaskDO productTask = productTaskMapper.selectOne(new QueryWrapper<ProductTaskDO>().eq("id", taskId));
        if (productTask == null) {
            log.warn("工作单不存在，重新投递，消息为: {}，", productMessage);
            return false;
        }
        // 判断是否为LOCK
        if (productTask.getLockState().equalsIgnoreCase(StockTaskStateEnum.LOCK.name())) {
            // 查询订单状态
            JsonData jsonData = productOrderFeignService.queryProductOrderState(outTradeNo);
            if (jsonData.getCode() == 0) {
                // 判断状态为NEW
                if (jsonData.getData().toString().equalsIgnoreCase(ProductOrderStateEnum.NEW.name())) {
                    // 下单后订单不可以为NEW，重新投递
                    log.warn("下单后订单不可以为NEW，重新投递，消息: {}", productMessage);
                    return false;
                }
                // 判断状态为PAY
                if (jsonData.getData().toString().equalsIgnoreCase(ProductOrderStateEnum.PAY.name())) {
                    //已经支付就把task状态改为从LOCK改为FINISH
                    log.info("已支付，task的状态由LOCK变为FINISH，消息体: {}", productMessage);
                    productTask.setLockState(StockTaskStateEnum.FINISH.name());
                    productTaskMapper.update(productTask, new QueryWrapper<ProductTaskDO>().eq("id", taskId));
                    return true;
                }
            }
            log.warn("订单不存在或订单被取消，消费一条消息，修改task状态为cancel，恢复商品库存，消息: {}", productMessage);
            productTask.setLockState(StockTaskStateEnum.CANCEL.name());
            productTaskMapper.update(productTask, new QueryWrapper<ProductTaskDO>().eq("id", taskId));
            // 恢复库存
            productMapper.unLockProductStock(productTask.getProductId(), productTask.getBuyNum());
            return true;
        } else {
            log.warn("工作单状态不为LOCK，消费了一条消息");
            return true;
        }
    }

    /**
     * do转换vo
     */
    private ProductVO beanProcess(ProductDO productDO) {
        ProductVO productVO = new ProductVO();
        BeanUtils.copyProperties(productDO, productVO);
        productVO.setStock(productDO.getStock() - productDO.getLockStock());
        return productVO;
    }

}
